summaryrefslogtreecommitdiff
path: root/src/passes/RemoveUnusedModuleElements.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/RemoveUnusedModuleElements.cpp')
-rw-r--r--src/passes/RemoveUnusedModuleElements.cpp50
1 files changed, 32 insertions, 18 deletions
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp
index 95318acd2..43236bf84 100644
--- a/src/passes/RemoveUnusedModuleElements.cpp
+++ b/src/passes/RemoveUnusedModuleElements.cpp
@@ -232,11 +232,11 @@ struct Analyzer {
// All the RefFuncs we've seen, grouped by heap type. When we see a CallRef of
// one of the types here, we know all the RefFuncs corresponding to it are
- // used. This is the reverse side of calledSignatures: for a function to
- // be used via a reference, we need the combination of a RefFunc of it as
- // well as a CallRef of that, and we may see them in any order. (Or, if the
- // RefFunc is in a table, we need a CallIndirect, which is handled in the
- // table logic.)
+ // potentially used (and also those of subtypes). This is the reverse side of
+ // calledSignatures: for a function to be used via a reference, we need the
+ // combination of a RefFunc of it as well as a CallRef of that, and we may see
+ // them in any order. (Or, if the RefFunc is in a table, we need a
+ // CallIndirect, which is handled in the table logic.)
//
// After we see a call for a type, we can clear out the entry here for it, as
// we'll have that type in calledSignatures, and so this contains only
@@ -326,24 +326,38 @@ struct Analyzer {
return worked;
}
+ std::optional<SubTypes> subTypes;
+
void useCallRefType(HeapType type) {
- // Call all the functions of that signature. We can then forget about
- // them, as this signature will be marked as called.
- auto iter = uncalledRefFuncMap.find(type);
- if (iter != uncalledRefFuncMap.end()) {
- // We must not have a type in both calledSignatures and
- // uncalledRefFuncMap: once it is called, we do not track RefFuncs for
- // it any more.
- assert(calledSignatures.count(type) == 0);
+ if (type.isBasic()) {
+ // Nothing to do for something like a bottom type; attempts to call such a
+ // type will trap at runtime.
+ return;
+ }
- for (Name target : iter->second) {
- use(ModuleElement(ModuleElementKind::Function, target));
+ if (!subTypes) {
+ subTypes = SubTypes(*module);
+ }
+
+ // Call all the functions of that signature, and subtypes. We can then
+ // forget about them, as those signatures will be marked as called.
+ for (auto subType : subTypes->getAllSubTypes(type)) {
+ auto iter = uncalledRefFuncMap.find(subType);
+ if (iter != uncalledRefFuncMap.end()) {
+ // We must not have a type in both calledSignatures and
+ // uncalledRefFuncMap: once it is called, we do not track RefFuncs for
+ // it any more.
+ assert(calledSignatures.count(subType) == 0);
+
+ for (Name target : iter->second) {
+ use(ModuleElement(ModuleElementKind::Function, target));
+ }
+
+ uncalledRefFuncMap.erase(iter);
}
- uncalledRefFuncMap.erase(iter);
+ calledSignatures.insert(subType);
}
-
- calledSignatures.insert(type);
}
void useRefFunc(Name func) {