Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 31 additions & 19 deletions src/ir/type-updating.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,43 +405,55 @@ void GlobalTypeRewriter::mapTypes(const TypeMap& oldToNewTypes) {
}

void GlobalTypeRewriter::mapTypeNamesAndIndices(const TypeMap& oldToNewTypes) {
// Track all the existing names to avoid creating duplicates.
std::unordered_set<Name> seenTypeNames;
for (auto& [type, info] : wasm.typeNames) {
seenTypeNames.insert(info.name);
}
// Collect new and updated type names and indices. Do not mutate the module's
// names and indices until the end to avoid iteration order affecting the
// results in the case where oldToNewTypes maps old types to different old
// types.
std::unordered_map<HeapType, TypeNames> newTypeNames;
std::unordered_map<HeapType, Index> newTypeIndices;

// Assign names and indices to new types. To avoid any dependencies on the
// iteration order, deterministically keep the lesser names or indices in the
// case of merges and do not mutate typeNames as we iterate over it.
for (auto& [old, new_] : oldToNewTypes) {
if (old == new_) {
// The type is being mapped to itself; no need to rename anything.
continue;
}
if (auto it = wasm.typeNames.find(old); it != wasm.typeNames.end()) {
auto& names = it->second;
newTypeNames[new_] = names;
// Use the existing name in the new type, as usually it completely
// replaces the old. Rename the old name in a unique way to avoid
// confusion in the case that it remains used.
auto deduped = Names::getValidName(
names.name, [&](Name test) { return !seenTypeNames.contains(test); });
names.name = deduped;
// Use `insert` to avoid overwriting the entry for the old type if it has
// already appeared as a new type.
if (newTypeNames.insert({old, names}).second) {
seenTypeNames.insert(names.name);
auto [newIt, inserted] = newTypeNames.insert({new_, names});
if (!inserted) {
if (names.name.view() < newIt->second.name.view()) {
newIt->second = names;
}
}
}
if (auto it = wasm.typeIndices.find(old); it != wasm.typeIndices.end()) {
// It's ok if we end up with duplicate indices. Ties will be resolved in
// some arbitrary manner.
newTypeIndices[new_] = it->second;
auto [newIt, inserted] = newTypeIndices.insert({new_, it->second});
if (!inserted) {
newIt->second = std::min(newIt->second, it->second);
}
}
}

// Assign old types that have been mapped to other types unique deduplicated
// names in case they remain used despite the mapping. In cases where the old
// types are also mapped _to_, the mapping will take precedence when we do the
// merge below.
std::unordered_set<Name> seenTypeNames;
for (auto& [_, names] : wasm.typeNames) {
seenTypeNames.insert(names.name);
}
for (auto& [type, names] : wasm.typeNames) {
if (auto it = oldToNewTypes.find(type);
it != oldToNewTypes.end() && it->second != type) {
names.name = Names::getValidName(names.name, [&](Name name) {
return seenTypeNames.insert(name).second;
});
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No test needed updating after this? Odd...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the only pass that merged types previously was TypeMerging, which I guess must handle this itself somehow.


newTypeNames.merge(wasm.typeNames);
wasm.typeNames = std::move(newTypeNames);
newTypeIndices.merge(wasm.typeIndices);
Expand Down
Loading